module ysyx_22040213_RegisterFile #(ADDR_WIDTH = 1, DATA_WIDTH = 1) (
	  input clk,
	  input rst,
	  input [DATA_WIDTH-1:0] wdata,
	  input [4:0] waddr,
	  input w_en,
	  input [4:0] rs1,
	  input [4:0] rs2,
	  output [DATA_WIDTH-1:0] src1,
	  output [DATA_WIDTH-1:0] src2,
	  //csr//
	  input ecall,
	  input [63:0] o_if_pc,
	  input [1:0]  csr_wen,
	  input [11:0] csr_rs1,
	  input [11:0] i_csr_waddr,
	  input [DATA_WIDTH-1:0] csr_wdata,
	  output [DATA_WIDTH-1:0] csr_src1,
	  output [DATA_WIDTH-1:0] mtvec,	
	  output [DATA_WIDTH-1:0] mepc,
	  //hand shake//
	  input out_allow,
	  input WB_to_REG_valid,
	  output REG_allow_in,
	  output valid_out,
	  // clint//
	  input clint_wen,
	  input clint_ren,
	  input clint_addr,
	  input [63:0] clint_wdata,
	  output reg [63:0] clint_rdata,
	  input [63:0] i_if_pc,
	  input ID_ready_go,
//	  input IF_ready_go,
	  output clint_trap_go,
//	  output clint_trap_go_diff,

	  //for difftest//
	  input [31:0] i_reg_inst,
	  input [63:0] i_reg_dnpc,
	  input i_reg_id_bubble,
	  input i_reg_exe_bubble,
	  input i_reg_valid,
	  input i_reg_devices_access,

	  output [31:0] o_reg_inst,
	  output [63:0] o_reg_dnpc,
	  output o_reg_id_bubble,
	  output o_reg_exe_bubble,
	  output o_reg_devices_access,
	  output o_reg_valid
  );

	reg [DATA_WIDTH-1:0] rf [ADDR_WIDTH-1:0];
	reg [DATA_WIDTH-1:0] rf_csr [7:0];
	wire [2:0] csr_waddr;
	wire [2:0] csr_rs1_o;
	reg [63:0] rf_clint [1:0]; //00 cmp 01 mtime 
	reg clint_trap;
	assign clint_trap_go = ID_ready_go && clint_trap;

	MuxKey #(6, 12, 3) i7 (csr_waddr, i_csr_waddr, {
		12'h305, 3'b000, //mtvec
		12'h341, 3'b001, //mepc
		12'h300, 3'b010, //mstatus
		12'h342, 3'b011, //mcause
		12'h304, 3'b100, //mie
		12'h344, 3'b101  //mip
		});
	MuxKey #(6, 12, 3) i8 (csr_rs1_o, csr_rs1, {
		12'h305, 3'b000, //mtvec
		12'h341, 3'b001, //mepc
		12'h300, 3'b010, //mstatus
		12'h342, 3'b011, //mcause
		12'h304, 3'b100, //mie
		12'h344, 3'b101  //mip
		});

	import "DPI-C" function void set_gpr_ptr(input logic [63:0] a []);
	initial set_gpr_ptr(rf);

	always @(posedge clk) begin    
	  if (w_en) rf[waddr] <= (waddr != 0) ? wdata : 0;
	  //csr//
	  if (csr_wen[0]) rf_csr[csr_waddr] <= csr_wdata;	
	  if (csr_wen[1]) rf_csr[csr_waddr] <= rf_csr[csr_waddr] | csr_wdata;
	  if (ecall) begin 
	    rf_csr[1] <= o_if_pc;
	    rf_csr[3] <= 64'd11;
    	  end else if(clint_trap_go)begin
	    rf_csr[1] <= i_if_pc;
	    rf_csr[3] <= 64'h8000000000000007;
    	  end 
	  //clint//
	  if (clint_wen) rf_clint[clint_addr] <= clint_wdata;
	  if (clint_ren) clint_rdata <= rf_clint[clint_addr];
	  if(rst)begin
	    rf_clint[1] <= 64'b0;
	    rf_clint[0] <= 64'b0;
	    clint_trap <= 1'b0;
	  end else if(rf_csr[4] == 64'h80) begin
	    rf_clint[1] <= rf_clint[1] +1;
          end
	  if(rf_csr[4] == 64'h80 && rf_clint[1] == rf_clint[0])begin
	     clint_trap <= 1'b1;
    	  end else if(ID_ready_go)begin
    	     clint_trap <= 1'b0;
	  end
  	end
	  
	  assign src1 = (rs1 != 0)? rf[rs1]:0;
	  assign src2 = (rs2 != 0)? rf[rs2]:0;

	  assign csr_src1 = rf_csr[csr_rs1_o];
	  assign mtvec    = rf_csr[0];
	  assign mepc     = rf_csr[1];
  
        //handshake//
	reg REG_valid;
	wire REG_ready_go = 1'b1;

	assign REG_allow_in = !REG_valid || REG_ready_go && out_allow; 
	assign valid_out = REG_valid;

	always @(posedge clk)begin
	  if(rst)begin
	    REG_valid <= 1'b0;
	  end
	  else if(REG_allow_in)begin
	    REG_valid <= WB_to_REG_valid;
	  end
	end

//	wire reg_w_en;
//	assign reg_w_en = WB_to_REG_valid && REG_allow_in;


	//for difftest//
	Reg #(32, 32'b0)  i0 (clk, rst, i_reg_inst, o_reg_inst, 1'b1);
	//Reg #(64, 64'h80000004)  i1 (clk, rst, i_reg_dnpc, delay_dnpc, 1'b1);
	Reg #(1,   1'b0)  i2 (clk, rst, i_reg_id_bubble, o_reg_id_bubble, 1'b1);
//	Reg #(1,   1'b0)  i3 (clk, rst, i_reg_exe_bubble, delay_exe_bubble, 1'b1);
	Reg #(1,   1'b0)  i5 (clk, rst, i_reg_valid, o_reg_valid, 1'b1);

	Reg #(64, 64'h80000004)  i4 (clk, rst, i_reg_dnpc, o_reg_dnpc, 1'b1);
	Reg #(1,   1'b0)  i6 (clk, rst, i_reg_exe_bubble, o_reg_exe_bubble, 1'b1);
	Reg #(1,   1'b0)  i9 (clk, rst, i_reg_devices_access, o_reg_devices_access, 1'b1);
//	assign o_reg_devices_access = i_reg_devices_access;

//	wire delay_exe_bubble;	
//	wire [63:0] delay_dnpc;
//	Reg #(64, 64'h80000004)  i4 (clk, rst, delay_dnpc, o_reg_dnpc, 1'b1);
//	Reg #(1,  1'b0)  i6(clk, rst, delay_exe_bubble, o_reg_exe_bubble, 1'b1);
endmodule
